/*
 * Copyright (c) 2008, Takashi Ito
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the authors nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _TANSU_SOCKET_H_
#define _TANSU_SOCKET_H_

#include "tansu_status.h"
#include "tansu_nwif.h"

#ifdef __cplusplus
extern "C" {
#endif

struct tansu_bound_socket {
	TAILQ_ENTRY(tansu_bound_socket) next;
    struct event bind_ev;
};
TAILQ_HEAD(tansu_bound_sockets, tansu_bound_socket);

tansu_status_t tansu_socket_close(int fd);

/**
 * Enables or disables nonblocking socket.
 *
 * @param[in] enabled 1 to enable nonblocking, or 0 to disable.
 *
 * @retval TANSU_SUCCESS
 * @retval TANSU_INVALID_ARGUMENT
 * @retval TANSU_FAILED
 */
tansu_status_t
tansu_socket_setnonblocking(int fd, int enabled);

/**
 * Creates an address string.
 * @note returned value must be deallocated by free().
 *
 * @param[in] ss
 *
 * @return address string
 */
char *
tansu_socket_getaddress(const struct sockaddr_storage *ss);

/**
 * Returns the socket length.
 */
socklen_t
tansu_socket_length(const struct sockaddr_storage *ss);

char *
tansu_socket_getlocal(const struct sockaddr_storage* remote);

/**
 * Retrieves the port number.
 *
 * @param[in] ss
 *
 * @return port number
 */
uint16_t
tansu_socket_getport(const struct sockaddr_storage *ss);

/**
 * @param[in]  fd
 * @param[out] ss
 *
 * @return socket descriptor or -1 on failure.
 */
int
tansu_socket_accept(int fd, struct sockaddr_storage* ss);

/**
 * @param[in] family
 * @param[in] type socket type (e.g. SOCK_DGRAM, SOCK_STREAM, SOCK_RAW)
 * @param[in] address
 * @param[in] port
 * @param[in] backlog
 * @param[out] status pointer to store error code when -1 is returned.
 *                    - TANSU_SUCCESS
 *                    - TANSU_INVALID_ARGUMENT
 *                    - TANSU_UNSUPPORTED
 *
 * @retval 0 on success
 * @retval -1 on failure
 */
int
tansu_socket_listen(int family,
                    int type,
                    const char *address,
                    uint16_t port,
                    int backlog,
                    tansu_status_t *status);

/**
 *
 */
tansu_status_t
tansu_socket_joingroup(int fd,
                       int family,
                       const char *group,
                       const char *ifaddr);

void
tansu_socket_joingroup_all(int fd,
                           int family,
                           const char *group,
                           struct tansu_nwifs *nwifs);

tansu_status_t
tansu_socket_set_multicast(int fd, int loop, int ttl, const char *mcastif);

tansu_status_t
tansu_socket_set_addr(int family,
                      struct sockaddr_storage *ss,
                      const char *addr,
                      uint16_t port);

tansu_status_t
tansu_socket_outaddr(const char *remote, struct sockaddr_storage *ss);

#ifdef __cplusplus
}
#endif

#endif /* _TANSU_SOCKET_H_ */

